package com.qiujianwei.study.authcenter.common.config;

import com.alibaba.fastjson.JSONObject;
import com.qiujianwei.study.authcenter.auth.AuthorizationManager;
import com.qiujianwei.study.authcenter.auth.CustomSecurityContextRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class WebSecurityConfig {

    @Bean
    public SecurityWebFilterChain customWebFilterChain(ServerHttpSecurity http,
                                                       CustomSecurityContextRepository customSecurityContextRepository){

        http
                .csrf().disable()
                .cors().disable()
                .httpBasic().disable()
                .securityContextRepository(customSecurityContextRepository)//这个对象如果使用new创建会导致@Awtowire注解失效
                .formLogin().and()
                .authorizeExchange()//请求进行授权
                .pathMatchers("/user-service/plogin","/user-service/clogin").permitAll()//登录不需要验证
                .anyExchange().access(new AuthorizationManager())//任何请求
                .and()
                .exceptionHandling()
                .accessDeniedHandler((exchange, denied) -> { // 无权限访问处理器(可以单独创建类处理)
                    Map<String, String> responseMap = new HashMap<>();
                    responseMap.put("code", "denied");
                    responseMap.put("msg", "账户无权限访问");
                    return writeWith(exchange, responseMap);
                });

        return http.build();

    }

    /**
     * 输出响应信息
     * @param exchange
     * @param responseMap
     * @return
     */
    public static Mono<Void> writeWith(ServerWebExchange exchange, Object responseMap){
        ServerHttpResponse response = exchange.getResponse();
        String body = JSONObject.toJSONString(responseMap);
        DataBuffer buffer = null;
        try{
            buffer = response.bufferFactory().wrap(body.getBytes("UTF-8"));
        }catch(UnsupportedEncodingException ue){
            ue.printStackTrace();
        }
        return response.writeWith(Mono.just(buffer));
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}
